from django.http import JsonResponse
from django.db.models import F
from django.db import IntegrityError, transaction

# 导入order对象定义
from common.models import Order, OrderMedicine

from django.core.paginator import Paginator, EmptyPage
from django.db.models import Q
import traceback
import json

# def dispatcher(request):
#     # 根据session判断用户是否登录的管理员用户
#     if 'usertype' not in request.session:
#         return JsonResponse({
#             'ret': 302,
#             'msg': '未登录',
#             'redirect': '/mgr/sign.html'
#         },
#         status = 302
#         )
#     if request.session['usertype'] != 'mgr':
#         return JsonResponse({
#             'ret': 302,
#             'msg': '用户非mgr类型',
#             'redirect': '/mgr/sign.html'
#         },
#         status = 302
#         )
    
#     # 将请求参数统一放入request的params属性中,方便后续处理
#     # get请求,参数在request对象的get属性中
#     if request.method == 'GET':
#         request.params = request.GET

#     # post/put/delete请求参数从request对象的body属性中获取
#     elif request.method in ['POST', 'put', 'DELETE']:
#         # 根据接口,请求的消息体都是json格式
#         request.params = json.loads(request.body)

#     # 根据不同的action分派给不同的函数进行处理
#     action = request.params['action']
#     if action == 'list_order':
#         return listorder(request)
#     elif action == 'add_order':
#         return addorder(request)
    
#     # 订单暂不支持修改和删除
#     else:
#         return JsonResponse({'ret': 0, 'msg': '不支持该类型的http请求'})
    
# def addorder(request):
    
#     info = request.params['data']

#     # 从请求消息中,获取要添加订单的信息
#     # 并且插入到数据库中

#     with transaction.atomic():
#         new_order = Order.objects.create(name = info['name'],
#                                          customer_id = info['customerid'])
#         batch = [OrderMedicine(order_id = new_order.id, medicine_id = mid, amount=1)
#                  for mid in info['medicineids']]
        
#         # 在多对多关系表中添加了多条关联记录
#         OrderMedicine.objects.bulk_create(batch)

#     return JsonResponse({'ret': 0, 'id': new_order.id})

def addorder(request):
    info = request.params['data']

    with transaction.atomic():
        medicinelist = info['medicinelist']

        new_order = Order.objects.create(name = info['name'],
                                         customer_id = info['customerid'],
                                        #  写入json格式的药品数据到medicinelist字段中
                                        medicinelist = json.dumps(medicinelist, ensure_ascii = False),)
        batch = [OrderMedicine(order_id = new_order.id,
                               medicine_id = medicine['id'],
                               amount = medicine['amount'])
                               for medicine in medicinelist]
        OrderMedicine.objects.bulk_create(batch)

    return JsonResponse({'ret': 0, 'id': new_order.id})

def listorder(request):
    try:
        # 返回一个queryset对象，包含所有的表记录
        qs = Order.objects\
            .annotate(
            customer_name = F('customer__name')
        )\
        .values(
            'id', 'name', 'create_date',
            'customer_name',
            'medicinelist'
        ).order_by('-id')

        # 查看是否有关键字搜索参数
        keywords = request.params.get('keywords', None)
        if keywords:
            conditions = [Q(name__contains = one) for one in keywords.split(' ') if one]
            query = Q()
            for condition in conditions:
                query &= condition
            qs = qs.filter(query)

        # 要获取的第几页
        pagenum = request.params['pagenum']
        # 每页要显示多少条记录
        pagesize = request.params['pagesize']
        # 使用分页对象，设定每页多少条记录
        pgnt = Paginator(qs, pagesize)
        # 从数据库中读取数据，指定读取其中第几页
        page = pgnt.page(pagenum)
        # 将queryset对象转化为list类型
        retlist = list(page)

        # total指定了一共有多少数据
        return JsonResponse({'ret': 0, 'retlist': retlist, 'total': pgnt.count})
    except EmptyPage:
        return JsonResponse({'ret': 0, 'retlist': [], 'total': 0})
    except:
        return JsonResponse({'ret': 2, 'msg': f'未知错误\n{traceback.format_exc()}'})

# def listorder(request):
#     qs = Order.objects \
#         .annotate(
#             customer_name = F('customer__name')
#         )\
#         .values(
#             'id', 'name', 'create_date',
#             'customer_name',
#             'medicine_list'
#         )
    
#     # 将queryset对象转换为List
#     retlist = list(qs)

#     return JsonResponse({'ret': 0, 'retlist': retlist})

def deleteorder(request):
    # 获取订单id
    oid = request.params['id']

    try:
        one = Order.objects.get(id = oid)
        with transaction.atomic():
            # 一定要先删除ordermedicine里面的记录
            OrderMedicine.objects.filter(order_id = oid).delete()
            # 再删除订单记录
            one.delete()

        return JsonResponse({'ret': 0, 'id': oid})
    except Order.DoesNotExist:
        return JsonResponse({
            'ret': 1,
            'msg': f'id为`{oid}`的订单不存在'
        })
    except:
        err = traceback.format_exc()
        return JsonResponse({'ret': 0, 'msg': err})

# def listorder(request):
#     # 返回一个queryset对象,包含所有的表记录
#     qs = Order.objects\
#         .annotate(
#             customer_name = F('customer__name'),
#             medicines_name = F('medicines__name')
#         )\
#         .values(
#             'id', 'name', 'create_date', 
#             # 两个下划线表示取customer外键关联的表中的name字段的值
#             # 'customer__name',
#             'customer_name',
#             # 两个下划线，表示取medicines 关联的表中的name字段的值
#             # 如果有多个，就会产生多条记录
#             # 'medicines__name'
#             'medicines_name')
#     # 将queryset对象转换为List对象
#     retlist = list(qs)
#     # retlist里的一个订单中,多个药品,会有多条记录,需要合并
#     newlist = []
#     id2order = {}
#     # 引用和副本
#     # Python 中的引用：id2order 和 newlist 都存储了对同一个字典对象的引用，因此对其中一个的修改会反映在另一个中。
#     # 解决方法：使用 copy() 方法创建对象的副本，避免共享同一个对象。
#     # 最佳实践：在处理复杂数据结构时，明确区分对象的引用和副本，避免意外的修改。
#     # 在 Python 中，id2order 和 newlist 的关系以及它们之间的修改行为
#     # 是由它们所引用的对象的性质决定的。具体来说，id2order 是一个字典，
#     # 而 newlist 是一个列表，它们都存储了对相同对象的引用。因此，
#     # 对 id2order 中对象的修改也会反映在 newlist 中。
#     for one in retlist:
#         orderid = one['id']
#         if orderid not in id2order:
#             newlist.append(one)
#             id2order[orderid] = one
#         else:
#             id2order[orderid]['medicines_name'] += '|' + one['medicines_name']

#     return JsonResponse({'ret': 0, 'retlist': newlist})

from lib.handler import dispatcherBase

Action2Handler = {
    'add_order': addorder,
    'list_order': listorder,
    'delete_order': deleteorder,
}

def dispatcher(request):
    return dispatcherBase(request, Action2Handler)